package com.topscomm.mis.cbb.file.compare.word.handler.impl;

import com.topscomm.mis.cbb.file.compare.cj.CjSystemConst;
import com.topscomm.mis.cbb.file.compare.cj.pojo.CjCompareJobResultEntity;
import com.topscomm.mis.cbb.file.compare.cj.pojo.dto.CompareItemsDto;
import com.topscomm.mis.cbb.file.compare.cj.pojo.dto.CompareParagraphStyleDto;
import com.topscomm.mis.cbb.file.compare.cj.pojo.dto.CompareTextStyleDto;
import com.topscomm.mis.cbb.file.compare.word.handler.BasicCompareHandler;
import com.topscomm.mis.cbb.file.compare.word.handler.IParagraphCompareHandler;
import com.topscomm.mis.cbb.file.compare.word.util.PoiWordUtil;
import com.topscomm.pub.util.ConvertUtil;
import com.topscomm.tap.common.DatacodeCache;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.ListIterator;

import java.util.Map;
import javafx.application.ConditionalFeature;
import javax.annotation.Resource;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

/**
 * @description:
 * @author: zhanglongfei
 * @date: 2023/2/22 15:48
 */
@Component
public class DefaultParagraphCompareHandler extends BasicCompareHandler implements
    IParagraphCompareHandler {

    /**
     * @param paragraph1:
     * @param paragraph2:
     * @param compareItemsDto: 2023-06-15 wxm添加参数：支持对比项自定义
     * @description: 比对两个段落差异，返回差异明细
     * @return: java.util.List<com.topscomm.mis.cbb.file.compare.cj.pojo.CjCompareJobResultEntity>
     * @author: zhanglongfei
     * @date: 2023/2/21 13:46
     * @modify:
     */
    @Override
    public List<CjCompareJobResultEntity> doCompare(XWPFParagraph paragraph1,
        XWPFParagraph paragraph2, IBody parent,
        CompareItemsDto compareItemsDto) {
        List<CjCompareJobResultEntity> resultList = new ArrayList<>();
        // 获取位置
        int paragraphNo = -1;
        if (parent instanceof XWPFDocument) {
            paragraphNo = PoiWordUtil.getParagraphPos((XWPFDocument) parent, paragraph1);
        } else if (parent instanceof XWPFTableCell) {
            paragraphNo = PoiWordUtil.getParagraphPos((XWPFTableCell) parent, paragraph1);
        }
        // 对比段落样式
        CjCompareJobResultEntity resultEntity = compareParagraphStyle(paragraph1, paragraph2,
            compareItemsDto);
        if (resultEntity != null) {
//            resultEntity.setPageno(paragraph1.getDocument());
            resultEntity.setParagraphno(paragraphNo);
            resultList.add(resultEntity);
        }
        // 对比文字内容
        resultEntity = compareText(paragraph1, paragraph2, compareItemsDto);
        if (resultEntity != null) {
            resultEntity.setParagraphno(paragraphNo);
            resultList.add(resultEntity);
        } else {
            this.restructureRun(paragraph1, paragraph2);
            // 对比run样式
            for (
                int i = 0, max = Math.min(paragraph1.getRuns().size(), paragraph2.getRuns().size());
                i < max; i++) {
                resultEntity = compareRunStyle(paragraph1.getRuns().get(i),
                    paragraph2.getRuns().get(i), compareItemsDto);
                if (resultEntity != null) {
                    resultEntity.setParagraphno(paragraphNo);
                    resultEntity.setRunno(i);
                    resultList.add(resultEntity);
                }
            }
        }
        return resultList;
    }

    /**
     * description 获取目标段落所在的页码
     *
     * @param document
     * @param targetParagraph
     * @return int
     * @author hdy
     * @date 2023-07-24
     * @modify
     */
    private int getParagraphPageNumber(XWPFDocument document, XWPFParagraph targetParagraph) {
        int pageNumber = 1;
        for (IBodyElement bodyElement : document.getBodyElements()) {
            if (bodyElement instanceof XWPFParagraph) {
                XWPFParagraph paragraph = (XWPFParagraph) bodyElement;
                if (paragraph == targetParagraph) {
                    break;
                }
            } else if (bodyElement instanceof XWPFSDT) {
                // 处理其他类型的内容，例如文本框（XWPFSDT）
            }
            pageNumber++;
        }
        return pageNumber;
    }

    /**
     * description run重组
     *
     * @param paragraph1
     * @param paragraph2
     * @return int
     * @author wxm
     * @date 2023-06-15 11:52:12
     * @modify
     */
    private void restructureRun(XWPFParagraph paragraph1, XWPFParagraph paragraph2) {
        if (paragraph1.getRuns().size() < 1 || paragraph2.getRuns().size() < 1) {
            return;
        }
        ListIterator<XWPFRun> iterator1 = paragraph1.getRuns().listIterator();
        ListIterator<XWPFRun> iterator2 = paragraph2.getRuns().listIterator();
        while (iterator1.hasNext() && iterator2.hasNext()) {
            XWPFRun run1 = iterator1.next();
            XWPFRun run2 = iterator2.next();
            if (run1.text().length() > run2.text().length()) {
                // 拆解run1
                String longRunNewText = this
                    .disassembleRun(paragraph1, run1, run2, iterator1.nextIndex());
                run1.setText(longRunNewText, 0);
                this.restructureRun(paragraph1, paragraph2);
                break;
            } else if (run1.text().length() < run2.text().length()) {
                // 拆解run2
                String longRunNewText = this
                    .disassembleRun(paragraph2, run2, run1, iterator2.nextIndex());
                run2.setText(longRunNewText, 0);
                this.restructureRun(paragraph1, paragraph2);
                break;
            }
        }
    }

    /**
     * description 拆解文本较长的run
     *
     * @param longRunParagraph
     * @param longRun
     * @param shortRun
     * @param index
     * @return java.lang.String
     * @author wxm
     * @date 2023-06-15 16:51:31
     * @modify
     */
    private String disassembleRun(XWPFParagraph longRunParagraph, XWPFRun longRun, XWPFRun shortRun,
        int index) {
        String longRunText = longRun.text();
        // 文字较长的run对应的新文字
        String longRunNewText = longRunText.substring(0, shortRun.text().length());
        // 文字较长的run拆出的新run对应的文字
        String longRunAddText = longRunText
            .substring(shortRun.text().length(), longRun.text().length());
        // 为longrun先设置新增run的内容进行复制，解决复制之后内容不能修改问题
        longRun.setText(longRunAddText, 0);
        // 新run
        CTR newCTR = null;
        try {
            newCTR = CTR.Factory.parse(longRun.getCTR().copy().toString());
        } catch (XmlException e) {
            e.printStackTrace();
        }
        // 插入新run，并设置原run的CTR备份，保留样式
        XWPFRun runAdd = longRunParagraph.insertNewRun(index);
        runAdd.getCTR().set(newCTR);
        return longRunNewText;
    }

    /**
     * @param paragraph1:
     * @param paragraph2:
     * @description: 比较文本差异
     * @return: com.topscomm.mis.cbb.file.compare.cj.pojo.CjCompareJobResultEntity
     * @author: zhanglongfei
     * @date: 2023/2/22 19:09
     * @modify:
     */
    private CjCompareJobResultEntity compareText(XWPFParagraph paragraph1,
        XWPFParagraph paragraph2, CompareItemsDto compareItemsDto) {
        DatacodeCache datacodeCache = new DatacodeCache();
        // 获取对照编码
        List<Map<String, Object>> symbolList = datacodeCache.getCodeListMap("CbbFileCompareSymbolCode"," enabled = 1 ");
//        Boolean symbolEquals = false;
        // 记录对比时的字符串
        String compareParagraph1 = paragraph1.getText();
        String compareParagraph2 = paragraph2.getText();
        // 如果查询到的配置不为空
        if (!CollectionUtils.isEmpty(symbolList)) {
            for (Map<String,Object> symbolMap : symbolList) {
                // 将当前对比的文本中的所有符号按照编码配置替换
                String code = ConvertUtil.convertToString(symbolMap.get("code"));
                String name = ConvertUtil.convertToString(symbolMap.get("name"));
                // 替换字符
                compareParagraph1 = compareParagraph1.replaceAll(code, name);
                compareParagraph2 = compareParagraph2.replaceAll(code, name);
//                // 替换后记录判断是否相同
//                if (ConvertUtil.convertToString(compareParagraph1).equals(compareParagraph2)) {
//                    // 相同时记录为相同
//                    symbolEquals = true;
//                }
            }
        }
        // 不对比或者无差异
        if (!Boolean.TRUE.equals(compareItemsDto.getCompareContent()) || compareParagraph1.replaceAll(" ","")
            .equals(compareParagraph2.replaceAll(" ",""))) {
            return null;
        }
        // 不对比或者无差异
        if (compareParagraph1.replaceAll("\n","").equals(compareParagraph2.replaceAll("\n",""))) {
            return null;
        }
        // 对比且有差异则记录
        CjCompareJobResultEntity resultEntity = createNewResultEntity();
        resultEntity.setDoccontent1("[文本内容]为：" + paragraph1.getText());
        resultEntity.setDoccontent2("[文本内容]为：" + paragraph2.getText());
        resultEntity.setDifftype(CjSystemConst.CjCompareJobResultDiffType.TextDiff);
        return resultEntity;
    }

    /**
     * @param paragraph1:
     * @param paragraph2:
     * @description: 比较Run差异
     * @return: com.topscomm.mis.cbb.file.compare.cj.pojo.CjCompareJobResultEntity
     * @author: zhanglongfei
     * @date: 2023/2/22 19:09
     * @modify:
     */
    private CjCompareJobResultEntity compareRunSize(XWPFParagraph paragraph1,
        XWPFParagraph paragraph2) {
        if (paragraph1.getRuns().size() == paragraph2.getRuns().size()) {
            return null;
        }
        CjCompareJobResultEntity resultEntity = createNewResultEntity();
        resultEntity.setDoccontent1("[文本块不一致]为：文本块" + paragraph1.getRuns().size());
        resultEntity.setDoccontent2("[文本块不一致]为：文本块" + paragraph2.getRuns().size());
        resultEntity.setDifftype(CjSystemConst.CjCompareJobResultDiffType.RunDiff);

        return resultEntity;
    }

    /**
     * @param paragraph1:
     * @param paragraph2:
     * @param compareItemsDto: 2023-06-14 wxm添加参数：支持对比项自定义
     * @description: 段落样式对比
     * @return: com.topscomm.mis.cbb.file.compare.cj.pojo.CjCompareJobResultEntity
     * @author: zhanglongfei
     * @date: 2023/2/22 19:09
     * @modify:
     */
    private CjCompareJobResultEntity compareParagraphStyle(XWPFParagraph paragraph1,
        XWPFParagraph paragraph2, CompareItemsDto compareItemsDto) {
        List<String> diffContent1 = new ArrayList<>();
        List<String> diffContent2 = new ArrayList<>();

        // 对比段落样式为空，则不对比段落样式
        if (compareItemsDto.getCompareParagraphStyleDto() == null) {
            return null;
        }

        CompareParagraphStyleDto paragraphStyleDto = compareItemsDto.getCompareParagraphStyleDto();
        // 如果对齐方式对比为true且对齐方式有差异，则记录差异
        if (Boolean.TRUE.equals(paragraphStyleDto.getAlignment())
            && paragraph1.getAlignment().compareTo(paragraph2.getAlignment()) != 0) {
            diffContent1.add("[对齐方式]为：" + paragraph1.getAlignment().name());
            diffContent2.add("[对齐方式]为：" + paragraph2.getAlignment().name());
        }
        if (Boolean.TRUE.equals(paragraphStyleDto.getFirstLineIndent())
            && paragraph1.getFirstLineIndent() != paragraph2.getFirstLineIndent()) {
            diffContent1.add("[首行缩进]为：" + paragraph1.getFirstLineIndent());
            diffContent2.add("[首行缩进]为：" + paragraph2.getFirstLineIndent());
        }
        if (Boolean.TRUE.equals(paragraphStyleDto.getFontAlignment())
            && paragraph1.getFontAlignment() != paragraph2.getFontAlignment()) {
            diffContent1.add("[文字对齐]为：" + paragraph1.getFontAlignment());
            diffContent2.add("[文字对齐]为：" + paragraph2.getFontAlignment());
        }
        if (Boolean.TRUE.equals(paragraphStyleDto.getSpacingBetween())
            && paragraph1.getSpacingBetween() != paragraph2.getSpacingBetween()) {
            diffContent1.add("[字间距]为：" + paragraph1.getSpacingBetween());
            diffContent2.add("[字间距]为：" + paragraph2.getSpacingBetween());
        }
        if (Boolean.TRUE.equals(paragraphStyleDto.getSpacingLineRule())
            && paragraph1.getSpacingLineRule().compareTo(paragraph2.getSpacingLineRule()) != 0) {
            diffContent1.add("[行间距]为：" + paragraph1.getSpacingLineRule().name());
            diffContent2.add("[行间距]为：" + paragraph2.getSpacingLineRule().name());
        }
        if (Boolean.TRUE.equals(paragraphStyleDto.getVerticalAlignment())
            && paragraph1.getVerticalAlignment().compareTo(paragraph2.getVerticalAlignment())
            != 0) {
            diffContent1.add("[垂直排列]为：" + paragraph1.getVerticalAlignment().name());
            diffContent2.add("[垂直排列]为：" + paragraph2.getVerticalAlignment().name());
        }
        if (Boolean.TRUE.equals(paragraphStyleDto.getPageBreak())
            && paragraph1.isPageBreak() != paragraph2.isPageBreak()) {
            diffContent1.add("[换页]为：" + paragraph1.isPageBreak());
            diffContent2.add("[换页]为：" + paragraph2.isPageBreak());
        }
        return getCjCompareJobResultEntity(diffContent1, diffContent2,
            CjSystemConst.CjCompareJobResultDiffType.StyleDiff);

    }


    /**
     * @param run1:
     * @param run2:
     * @param compareItemsDto: 2023-06-15 wxm添加参数：支持对比项自定义
     * @description: 比较Run样式差异
     * @return: com.topscomm.mis.cbb.file.compare.cj.pojo.CjCompareJobResultEntity
     * @author: zhanglongfei
     * @date: 2023/2/22 19:09
     * @modify:
     */
    private CjCompareJobResultEntity compareRunStyle(XWPFRun run1, XWPFRun run2,
        CompareItemsDto compareItemsDto) {
        List<String> diffContent1 = new ArrayList<>();
        List<String> diffContent2 = new ArrayList<>();
        // 若样式比对为空或文本样式比对为空
        if (compareItemsDto.getCompareTextStyleDto() == null) {
            return null;
        }
        CompareTextStyleDto compareTextStyleDto = compareItemsDto.getCompareTextStyleDto();

        // 对比加粗且有差异
        if (Boolean.TRUE.equals(compareTextStyleDto.getBold()) && run1.isBold() != run2.isBold()) {
            diffContent1.add("[加粗]为：" + run1.isBold());
            diffContent2.add("[加粗]为：" + run2.isBold());
        }
        // 对比双删除线且有差异
        if (Boolean.TRUE.equals(compareTextStyleDto.getDoubleStrikeThrough())
            && run1.isDoubleStrikeThrough() != run2.isDoubleStrikeThrough()) {
            diffContent1.add("[双删除线]为：" + run1.isDoubleStrikeThrough());
            diffContent2.add("[双删除线]为：" + run2.isDoubleStrikeThrough());
        }
        // 对比斜体且有差异
        if (Boolean.TRUE.equals(compareTextStyleDto.getItalic()) && run1.isItalic() != run2
            .isItalic()) {
            diffContent1.add("[斜体]为：" + run1.isItalic());
            diffContent2.add("[斜体]为：" + run2.isItalic());
        }
        // 对比删除线且有差异
        if (Boolean.TRUE.equals(compareTextStyleDto.getStrikeThrough())
            && run1.isStrikeThrough() != run2.isStrikeThrough()) {
            diffContent1.add("[删除线]为：" + run1.isStrikeThrough());
            diffContent2.add("[删除线]为：" + run2.isStrikeThrough());
        }
        // 对比颜色且有差异
        if (Boolean.TRUE.equals(compareTextStyleDto.getColor()) && !toString(run1.getColor())
            .equals(toString(run2.getColor()))) {
            diffContent1.add("[颜色]为：" + run1.getColor());
            diffContent2.add("[颜色]为：" + run2.getColor());
        }
        // 对比字符间距且有差异
        if (Boolean.TRUE.equals(compareTextStyleDto.getCharacterSpacing())
            && run1.getCharacterSpacing() != run2.getCharacterSpacing()) {
            diffContent1.add("[字符间距]为：" + run1.getCharacterSpacing());
            diffContent2.add("[字符间距]为：" + run2.getCharacterSpacing());
        }
        // 对比字体且有差异
        if (Boolean.TRUE.equals(compareTextStyleDto.getFontFamily()) && !toString(
            run1.getFontFamily()).equals(toString(run2.getFontFamily()))) {
            diffContent1.add("[字体]为：" + run1.getFontFamily());
            diffContent2.add("[字体]为：" + run2.getFontFamily());
        }
        // 对比字体类型且有差异
        if (Boolean.TRUE.equals(compareTextStyleDto.getFontName()) && !toString(run1.getFontName())
            .equals(toString(run2.getFontName()))) {
            diffContent1.add("[字体类型]为：" + run1.getFontName());
            diffContent2.add("[字体类型]为：" + run2.getFontName());
        }
        // 对比字体大小且有差异
        if (Boolean.TRUE.equals(compareTextStyleDto.getFontSize())
            && run1.getFontSizeAsDouble() != null && run2.getFontSizeAsDouble() != null
            && run1.getFontSizeAsDouble().compareTo(run2.getFontSizeAsDouble()) != 0) {
            diffContent1.add("[字体大小]为：" + run1.getFontSizeAsDouble());
            diffContent2.add("[字体大小]为：" + run2.getFontSizeAsDouble());
        }
        // 对比字间距且有差异
        if (Boolean.TRUE.equals(compareTextStyleDto.getKerning()) && run1.getKerning() != run2
            .getKerning()) {
            diffContent1.add("[字间距]为：" + run1.getKerning());
            diffContent2.add("[字间距]为：" + run2.getKerning());
        }
        // 对比下划线且有差异
        if (Boolean.TRUE.equals(compareTextStyleDto.getUnderline())
            && run1.getUnderline().compareTo(run2.getUnderline()) != 0) {
            diffContent1.add("[下划线]为：" + run1.getUnderline().name());
            diffContent2.add("[下划线]为：" + run2.getUnderline().name());
        }
        return getCjCompareJobResultEntity(diffContent1, diffContent2,
            CjSystemConst.CjCompareJobResultDiffType.StyleDiff);
    }
}
